package com.bolt.admin.module.sys.service;


import com.bolt.admin.constant.CacheKey;
import com.bolt.admin.module.sys.dto.RoleDTO;
import com.bolt.admin.module.sys.entity.PrivilegeEntity;
import com.bolt.admin.module.sys.entity.RoleEntity;
import com.bolt.admin.module.sys.entity.UserEntity;
import com.bolt.admin.module.sys.repository.RoleRepository;
import com.bolt.admin.module.sys.repository.UserR2RoleRepository;
import com.bolt.admin.module.sys.service.converter.RoleConverter;
import com.bolt.common.utils.StrUtil;
import com.bolt.convention.data.code.CommonCode;
import com.bolt.convention.exception.ServiceException;
import com.bolt.support.base.service.BaseService;
import com.bolt.support.cache.redis.RedisManager;
import com.bolt.support.spring.jpa.filter.FilterBuilder;
import com.bolt.support.spring.jpa.jpql.Clauses;
import com.bolt.support.spring.jpa.repository.BasicJpaRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * Auto Generate Javadoc
 *
 * @author 日期:2018-02-26 17:21:27
 *         角色信息
 **/
@Service
@Transactional(readOnly = true, rollbackFor = Exception.class)
public class RoleService extends BaseService<RoleEntity, String> {

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private PrivilegeService privilegeService;

    @Autowired
    private UserR2RoleRepository userR2RoleRepository;

    @Autowired
    private RedisManager redisManager;

    @Override
    protected BasicJpaRepository<RoleEntity, String> getRepository() {
        return roleRepository;
    }

    public List <String> findPrivileges(String roleId) {
        List <PrivilegeEntity> privilegeEntities = privilegeService.findPrivileges(roleId);
        return privilegeEntities.stream().map(k -> k.getId()).collect(Collectors.toList());
    }


    public List <RoleDTO> getAllRoleData() {
        return this.jpaQueryFactory.select(RoleDTO.class,
                Clauses.of(RoleEntity::getId),
                Clauses.of(RoleEntity::getName)
        ).from(Clauses.of(RoleEntity.class))
                .orderBy(Clauses.of(RoleEntity::getCode).desc()).fetch();
    }


    public List <RoleEntity> findRoles(UserEntity user) {
        return roleRepository.findRolesByUser(user);
    }

    public List <RoleEntity> findRoles(String userId) {
        return roleRepository.findRolesByUserId(userId);
    }


    @Transactional(rollbackFor = Exception.class)
    public RoleEntity save(RoleDTO dto) {
        RoleEntity entity = RoleConverter.toEntity(dto);
        if (StrUtil.isEmpty(entity.getCode()) || entity.getCode().length() < 6) {
            throw new ServiceException("500", "角色编码不能未空且长度必须大于6小于 64。");
        }
        List <RoleEntity> roleList = findAll(new FilterBuilder<RoleEntity>()
                .lambda().eq(RoleEntity::getCode, entity.getCode()).build());
        if (roleList.size() > 0) {
            throw new ServiceException("500", "角色编码【" + entity.getCode() + "】已存在！");
        }
        save(entity);
        return entity;
    }

    @Transactional(rollbackFor = Exception.class)
    public RoleEntity update(RoleDTO dto ){

        Optional<RoleEntity> optional = findOne(dto.getId());
        RoleEntity entity;
        if (!optional.isPresent()) {
         throw new ServiceException("500", "查询记录的出错！");
        } else {
            entity = optional.get();
        }
        if (!entity.getCode().equals(entity.getCode())) {
           throw new ServiceException("500", "原角色编码【" + entity.getCode() + "】不能修改为【" + entity.getCode() + "】！");
        }
        entity = RoleConverter.toEntity(entity,dto);
        save(entity);
        delCaches(entity.getId());
        return entity;
    }

    /**
     * 根据角色id查询用户列表
     *
     * @param roleId
     * @return 0：没有用户为该角色；
     * 其他：所有用户名称，以逗号分割
     */
    public String getUserNamesByRoleId(String roleId) {
        String result = "0";
        List <UserEntity> userList = userR2RoleRepository.findUserByRoleId(roleId);
        for (UserEntity user : userList) {
            if ("0".equals(result)) {
                result = user.getRealName();
            } else {
                result += "," + user.getRealName();
            }
        }
        return result;

    }


    @Transactional
    public RoleEntity updateRelatedPrivilege(String roleId, String[] privilegeIds) {
        RoleEntity entity = roleRepository.findById(roleId)
                .orElseThrow(() -> new ServiceException(CommonCode.DATA_NOT_FOUND));
        super.updateRelatedR2s(entity, privilegeIds, "roleR2Privileges", "privilege");
        delCaches(roleId);
        return entity;
    }

    private void delCaches(String roleId) {
        List <UserEntity> userEntities = userR2RoleRepository.findUserByRoleId(roleId);
        List <String> userIds = userEntities.stream().map(k -> k.getId()).collect(Collectors.toList());
        for(String userId : userIds){
            redisManager.del(CacheKey.USER_ID+userId);
        }

    }
}
